package cn.lili.modules.promotion.serviceimpl;

import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.crypto.digest.MD5;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.properties.ApiProperties;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.promotion.entity.dos.GreenCommonwealContribution;
import cn.lili.modules.promotion.mapper.GreenCommonwealContributionMapper;
import cn.lili.modules.promotion.service.GreenCommonwealContributionService;
import cn.lili.modules.promotion.service.GreenProjectService;
import cn.lili.mybatis.util.PageUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.api.PayApi;
import com.api.UserApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pojos.OpenAppUser;
import com.pojos.OrderModel;
import com.pojos.UserRes;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class GreenCommonwealContributionServiceImpl
        extends ServiceImpl<GreenCommonwealContributionMapper, GreenCommonwealContribution>
        implements GreenCommonwealContributionService {

    private final PayApi payApi;

    private final UserApi userApi;

    private final ApiProperties apiProperties;

    @Value("${fw.appid}")
    String appId;

    @Value("${fw.secrect}")
    String secret;

    private final GreenProjectService greenProjectService;

    /**
     * 分页获取用户捐赠数据
     * @param pageVO
     * @return
     */
    @Override
    public Map<String, Object> getPage (PageVO pageVO) {
        Map<String, Object> resultMap = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        LambdaQueryWrapper<GreenCommonwealContribution> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GreenCommonwealContribution::getStatus, 1);
        queryWrapper.eq(GreenCommonwealContribution::getContributionType, 1);
        queryWrapper.eq(GreenCommonwealContribution::getDeleteFlag, false);
        queryWrapper.orderByDesc(GreenCommonwealContribution::getCreateTime);
        Page<GreenCommonwealContribution> page = this.page(PageUtil.initPage(pageVO), queryWrapper);
        if (!page.getRecords().isEmpty()) {
            page.getRecords().forEach(greenCommonwealContribution -> {
                greenCommonwealContribution.setCreateDate(sdf.format(greenCommonwealContribution.getCreateTime()));
            });
            Map<String, List<GreenCommonwealContribution>> map = page.getRecords().stream().collect(Collectors.groupingBy(GreenCommonwealContribution::getCreateDate));
            Map<String, List<GreenCommonwealContribution>> sortMap = greenProjectService.sortByKey(map, true);
            resultMap.put("count", page.getTotal());
            resultMap.put("data", sortMap);
        }else {
            resultMap.put("data", new HashMap<>());
        }
        return resultMap;
    }

    /**
     * 获取用户绿色积分余额
     * @return
     */
    @Override
    public String getBalance () {
        UserRes userRes = payApi.getUserMoney(UserContext.getCurrentUser().getOpenId());
        if (null == userRes) {
            return null;
        }
        return userRes.getGmoney();
    }

    /**
     * 用户捐赠
     * @param openId
     * @param money
     * @return
     */
    @Override
    public Map<String, Object> add (String openId, String money) {
        // 获取用户绿色积分余额
        UserRes userRes = payApi.getUserMoney(openId);
        if (new BigDecimal(userRes.getGmoney()).compareTo(new BigDecimal(money)) <= 0) {
            throw new ServiceException("绿色积分不足");
        }
        // 创建支付订单
        String orderNo = UUID.randomUUID().toString().replaceAll("-", "");
        int jzMoney = Integer.parseInt(money) * 100;
        Map<String, Object> params = payInfo(appId, Objects.requireNonNull(UserContext.getCurrentUser()).getOpenId(), secret,
                "商城用户：" + Objects.requireNonNull(UserContext.getCurrentUser()).getUsername() + "，捐赠绿色积分" + money,
                jzMoney, orderNo, 2, 3,
                apiProperties.getBuyer() + "/promotion/gc/contribution/callback");
        JSONObject result = payApi.createPayOrderV3(params);
        if (result.getInteger("code") != 200) {
            if (result.getInteger("code") == 10008){
                throw new ServiceException(ResultCode.NAME_OUTH,result.getString("msg"));
            }else{
                throw new ServiceException(result.getString("msg"));
            }
        }

        GreenCommonwealContribution contribution = new GreenCommonwealContribution();
        contribution.setOpenId(openId);
        contribution.setUserId(UserContext.getCurrentId());
        contribution.setContributionMoney(BigDecimal.valueOf(jzMoney));
        contribution.setOrderNo(orderNo);
        contribution.setStatus(0);
        contribution.setUserName(UserContext.getCurrentUser().getUsername());
        contribution.setContributionType(1);
        contribution.setCreateTime(new Date());
        contribution.setGcType(1);
        contribution.setRemarks("用户" + UserContext.getCurrentUser().getUsername() +
                "捐助" + money + "绿色积分");
        this.baseMapper.insert(contribution);
        return params;
    }

    @Override
    public String callback (OrderModel orderModel) {
        /*if (!vertify(orderModel, "a78s9dd78s9ads1031")) {
            throw new ServiceException("非法请求");
        }*/
        GreenCommonwealContribution gcContribution = getByOrderNo(orderModel.getOrderno());
        if (null == gcContribution) {
            return "订单数据异常";
        }
        //Integer gMoney = gcContribution.getContributionMoney().intValue() * 100;
        //BigDecimal gMoney = gcContribution.getContributionMoney().multiply(new BigDecimal("100"));
        boolean payResult = payApi.paymentFromUser(appId, gcContribution.getOpenId(),
                "商城用户：" + gcContribution.getUserName() + "[" + gcContribution.getId() + "]，通过绿色公益捐赠绿色积分" + (gcContribution.getContributionMoney().divide(new BigDecimal("100"))),
                gcContribution.getContributionMoney().stripTrailingZeros().toPlainString(), "GMONEY", "fy_ds7d8s9a1031", "a78s9dd78s9ads1031");
        if (payResult) {
            gcContribution.setStatus(1);
            this.baseMapper.updateById(gcContribution);
            return null;
        }else {
            gcContribution.setStatus(2);
            this.baseMapper.updateById(gcContribution);
            throw new ServiceException("订单异常");
        }
    }

    public GreenCommonwealContribution getByOrderNo (String orderNo) {
        LambdaQueryWrapper<GreenCommonwealContribution> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GreenCommonwealContribution::getOrderNo, orderNo);
        queryWrapper.last("limit 1");
        return this.baseMapper.selectOne(queryWrapper);
    }

    /**
     * 用户购买公益商品分佣到绿色公益账户
     * @param greenCommonwealContribution
     */
    @Override
    public void contribution (GreenCommonwealContribution greenCommonwealContribution) {
        if (StringUtil.isEmpty(greenCommonwealContribution.getOpenId()) ||
                null == greenCommonwealContribution.getContributionMoney()) {
            throw new ServiceException(ResultCode.PARAMS_ERROR);
        }
        OpenAppUser openAppUser = userApi.getOtherUserInfoByOpenId("fy_ds7d8s9a1031", greenCommonwealContribution.getOpenId());
        if (null == openAppUser) {
            log.info("调用飞语第三方接口创建用户失败");
            throw new ServiceException("创建公益用户失败");
        }
        greenCommonwealContribution.setContributionType(1);
        greenCommonwealContribution.setCreateTime(new Date());
        greenCommonwealContribution.setStatus(1);
        greenCommonwealContribution.setGcType(0);
        BigDecimal money = greenCommonwealContribution.getContributionMoney().multiply(new BigDecimal("100"));
        if (payApi.paymentFromUser(appId,greenCommonwealContribution.getOpenId(), greenCommonwealContribution.getRemarks(),
                money.stripTrailingZeros().toPlainString(),"GMONEY", "fy_ds7d8s9a1031", "a78s9dd78s9ads1031")) {
            greenCommonwealContribution.setContributionMoney(money);
            greenCommonwealContribution.setRemarks("用户" + greenCommonwealContribution.getUserName() + "购买商品");
            this.save(greenCommonwealContribution);
        }
    }

    /**
     * 分页查询捐赠记录
     * @param contribution
     * @param pageVO
     * @return
     */
    @Override
    public Page<GreenCommonwealContribution> getPageByParams (GreenCommonwealContribution contribution, PageVO pageVO) {
        LambdaQueryWrapper<GreenCommonwealContribution> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GreenCommonwealContribution::getStatus, 1);
        queryWrapper.eq(null != contribution.getContributionType(), GreenCommonwealContribution::getContributionType, contribution.getContributionType());
        queryWrapper.ge(null != contribution.getStartTime(), GreenCommonwealContribution::getCreateTime, contribution.getStartTime());
        queryWrapper.le(null != contribution.getEndTime(), GreenCommonwealContribution::getCreateTime, contribution.getEndTime());
        queryWrapper.like(StringUtils.isNotEmpty(contribution.getRemarks()), GreenCommonwealContribution::getRemarks, contribution.getRemarks());
        queryWrapper.orderByDesc(GreenCommonwealContribution::getCreateTime);
        return this.page(PageUtil.initPage(pageVO), queryWrapper);
    }

    /**
     * 分页查询捐赠记录
     * @param contribution
     * @param pageVO
     * @return
     */
    @Override
    public Page<GreenCommonwealContribution> getContributionPage (GreenCommonwealContribution contribution, PageVO pageVO) {
        LambdaQueryWrapper<GreenCommonwealContribution> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(null != contribution.getType() && contribution.getType() == 1, GreenCommonwealContribution::getOpenId, UserContext.getCurrentUser().getOpenId());
        queryWrapper.eq(GreenCommonwealContribution::getStatus, 1);
        queryWrapper.eq(GreenCommonwealContribution::getGcType, 1);
        queryWrapper.orderByDesc(GreenCommonwealContribution::getCreateTime);
        return this.page(PageUtil.initPage(pageVO), queryWrapper);
    }


    public JSONObject payInfo(String appId, String openId, String secret, String attach, Integer totalFee, String orderNo, Integer tradeType, Integer operationType, String callBack){
        Long timestamp = System.currentTimeMillis();
        String str = String.format("appid=%s&paternerKey=%s&total_fee=%s&out_trade_no=%s&trade_type=%s&timestamp=%s&operation_type=%s&callback=%s&type=%s",
                appId, secret, totalFee, orderNo, tradeType, timestamp, operationType, callBack, "GMONEY");
        Digester sha1 = new Digester(DigestAlgorithm.SHA1);
        String sign = sha1.digestHex(MD5.create().digestHex(str));

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appid", appId);
        jsonObject.put("account", openId);
        jsonObject.put("total_fee", totalFee);
        jsonObject.put("out_trade_no", orderNo);
        jsonObject.put("trade_type", tradeType);
        jsonObject.put("timestamp", timestamp);
        jsonObject.put("operation_type", operationType);
        jsonObject.put("sign", sign);
        jsonObject.put("remark", attach);
        jsonObject.put("callback_url", callBack);
        jsonObject.put("type", "GMONEY");
        jsonObject.put("version", "3");
        //jsonObject.put("gmoney", gMoney);
        return jsonObject;
    }

    public static boolean vertify(OrderModel orderMessage, String secret){
        String nSign = MD5.create().digestHex(String.format("account=%s&appid=%s&money=%s&secret=%s", orderMessage.getAccount(), orderMessage.getAppid(), orderMessage.getMoney(), secret));

        System.out.println(orderMessage.getSign());
        System.out.println(nSign);
        return nSign.equals(orderMessage.getSign());
    }

    /**
     * 获取用户绿色积分余额
     * @return
     */
    @Override
    public String getUserBalance () {
        UserRes userRes = payApi.getUserMoney(UserContext.getCurrentUser().getOpenId());
        if (null != userRes) {
            return userRes.getGmoney();
        }
        return null;
    }
}
